#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Version: Python 2.6.6
# Author: Sergey K.
# Created: 2011-08-15


import unittest
import json

import common

import rs.status
import rs.response


class ResponseTest(unittest.TestCase):

    def test_init(self):
        response = rs.response.Response()
        eq = self.assertEquals
        eq(None, response.status)
        eq({}, response.headers)
        eq(None, response.entity)
        response = rs.response.Response(rs.status.NO_CONTENT)
        eq(rs.status.NO_CONTENT, response.status)
        eq({}, response.headers)
        eq(None, response.entity)


class ResponseBuilderTest(unittest.TestCase):

    def test_init(self):
        eq = self.assertEquals
        true = self.assertTrue
        response = None
        builder = rs.response.ResponseBuilder(response)
        eq(204,  builder.status)
        true(builder.entity is None)
        true(builder.headers is None)
        true(builder.tag is None)
        true(builder.cache is None)
        response = object()
        builder = rs.response.ResponseBuilder(response)
        eq(200,  builder.status)
        true(builder.entity is response)
        true(builder.headers is None)
        true(builder.tag is None)
        true(builder.cache is None)
        response = ('entity', 201, {'Location':'/uri'})
        builder = rs.response.ResponseBuilder(response)
        eq(201,  builder.status)
        eq('entity', builder.entity)
        true('Location' in builder.headers)
        eq('/uri', builder.headers['Location'])
        true(builder.tag is None)
        true(builder.cache is None)

    def test_build(self):
        eq = self.assertEquals
        true = self.assertTrue
        e = {'id':0, 'names':None}
        builder = rs.response.ResponseBuilder(e)
        response = builder.build((None, str))
        eq(200, response.status)
        eq(str(e), response.entity)
        eq(2, len(response.headers)) # Content-Type, Content-Length
        response = builder.build(('application/json', json.dumps))
        eq(200, response.status)
        eq(json.dumps(e), response.entity)
        eq(2, len(response.headers))
        true(response.headers['content-type'].startswith('application/json'))

    def test_build_tag(self):
        from rs.cache import Tag
        eq = self.assertEquals
        true = self.assertTrue
        producer = (None, str)
        e = {'id':0, 'names':None}
        builder = rs.response.ResponseBuilder(e)
        tag = Tag(etag=lambda e: hash(repr(e)))
        builder.set_tag(tag)
        response = builder.build(producer)
        true('etag' in response.headers)
        true('last-modified' not in response.headers)
        eq('"{0}"'.format(hash(repr(e))), response.headers['etag'])
        tag = Tag(etag=lambda entity: entity['id'],
                  last_modified=lambda entity: '123')
        builder.set_tag(tag)
        response = builder.build(producer)
        true('etag' in response.headers)
        true('last-modified' in response.headers)
        eq('"{0}"'.format(e['id']), response.headers['etag'])
        eq('123', response.headers['last-modified'])
        builder = rs.response.ResponseBuilder((e, 201, {'ETag':'Priority'}))
        builder.set_tag(tag)
        response = builder.build(producer)
        true('etag' in response.headers)
        eq('Priority', response.headers['etag'])

    def test_build_cache(self):
        from rs.cache import CacheControl
        eq = self.assertEquals
        true = self.assertTrue
        producer = (None, str)
        e = {'id':0, 'names':None}
        builder = rs.response.ResponseBuilder(e)
        cache = CacheControl(maxage='', data='')
        builder.set_cache(cache)
        response = builder.build(producer)
        true('cache-control' in response.headers)
        eq('no-cache', response.headers['cache-control'])
        cache = CacheControl(maxage=1000, data='')
        builder.set_cache(cache)
        response = builder.build(producer)
        true('cache-control' in response.headers)
        eq('private, max-age=1000', response.headers['cache-control'])
        cache = rs.cache.CacheControl(maxage='1000', data='private,no-store')
        builder.set_cache(cache)
        response = builder.build(producer)
        true('cache-control' in response.headers)
        eq('no-store, private, max-age=1000', response.headers['cache-control'])

    def test_make_response(self):
        eq = self.assertEquals
        builder = common.dummy()
        rs.response.make_response(builder)
        eq(None, builder.entity)
        eq(204, builder.status)
        eq(None, builder.headers)
        rs.response.make_response(builder, 'entity')
        eq('entity', builder.entity)
        eq(200, builder.status)
        eq(None, builder.headers)
        rs.response.make_response(builder, 'entity', 201, {'Location':'/location'})
        eq('entity', builder.entity)
        eq(201, builder.status)
        eq('/location', builder.headers['Location'])

    def test_make_error_response(self):
        eq = self.assertEquals
        builder = common.dummy()
        make_response = rs.response.make_error_response(404)
        make_response(builder)
        eq(None, builder.entity)
        eq(404, builder.status)
        eq(None, builder.headers)
        make_response(builder, 'e')
        eq('e', builder.entity)
        eq(404, builder.status)
        eq(None, builder.headers)
        make_response(builder, 'e', None, {'h':'v'})
        eq('e', builder.entity)
        eq(404, builder.status)
        eq('v', builder.headers['h'])
        make_response(builder, 'e', 400, {'h':'v'})
        eq('e', builder.entity)
        eq(400, builder.status)
        eq('v', builder.headers['h'])


if __name__ == '__main__':
    unittest.main()